package day02;


/**
 * while (true) {
 *                 int o = account.balance;
 *                 int n = o + 5;
 *                 if (U.compareAndSwapInt(account, BALANCE, o, n)) {
 *                     break;
 *                 }
 *             } 这一段代码什么意思啊
 *
 *
 *             这段代码是一个使用了乐观锁机制的循环，用于尝试对account对象的balance属性进行原子性的更新。让我们逐步解析：
 *
 *             while (true) {
             *     int o = account.balance; // 读取当前余额
             *     int n = o + 5;          // 新余额等于旧余额加5
             *     if (U.compareAndSwapInt(account, BALANCE, o, n)) {
             *         break; // 如果更新成功，则跳出循环
             *     }
             * }
 *
 *
 * while (true)：创建一个无限循环，直到满足特定条件才会退出。
 * int o = account.balance;：这里假设account是一个表示账户的对象，balance是该对象中的一个字段，代表账户余额。这行代码获取当前余额，并将其存储在局部变量o中。
 * int n = o + 5;：计算新的余额值，即在原有基础上增加5个单位（可能是货币单位）。
 * if (U.compareAndSwapInt(account, BALANCE, o, n)) { ... }：这是最关键的部分。compareAndSwapInt（通常缩写为CAS）是一种原子操作，它会检查account对象的BALANCE字段是否仍然等于o（预期的旧值），如果是，则将BALANCE设置为新值n。这个操作是原子性的，意味着它是不可分割的整体，不会被其他线程打断。如果操作成功，那么compareAndSwapInt方法返回true，程序执行break语句，退出循环；如果失败（因为其他线程可能已经改变了余额），则返回false，循环继续下一次迭代，重新读取余额并再次尝试更新。
 * 这种模式常用于并发编程中，以避免使用传统的锁定机制（如synchronized关键字），从而减少死锁和提高性能。但是，需要注意的是，如果存在高争用的情况，即多个线程频繁地试图更新同一个账户的余额，这个循环可能会导致较高的CPU利用率，因为失败的线程会不断重试。
 *
 * 请注意，实际的Java代码实现中，U.compareAndSwapInt可能是Unsafe类的一个方法，或者是使用了AtomicInteger等类似的原子类型提供的类似方法来实现。在使用Unsafe类时，必须非常谨慎，因为它可以绕过Java的安全检查。
 *
 * 代码模式
 *
 *
 * 它会检查account对象的BALANCE字段是否仍然等于o，这是啥意思啊，    static class Account {
 *         volatile int balance = 10;
 *     } 这是account，他没有叫做BALANCE的字段啊，
 *
 *
 *     您是对的，根据您给出的Account类定义，它确实只有一个名为balance的字段，并没有名为BALANCE的字段。在您的代码片段中提到的BALANCE，通常是用来表示一个偏移量（offset），这个偏移量指定了balance字段相对于对象起始地址的位置。
 *
 * 在Java中，使用Unsafe类进行底层操作时，通常需要获取字段的内存偏移量来执行CAS操作。为了得到这个偏移量，一般会使用Unsafe类的objectFieldOffset方法。因此，BALANCE应该是一个静态变量，保存了通过反射机制获得的balance字段的偏移量。
 *
 * 以下是如何正确地设置和使用BALANCE变量的一个示例：
 *import sun.misc.Unsafe;
 *
 * import java.lang.reflect.Field;
 *
 * public class Example {
 *     static class Account {
 *         volatile int balance = 10;
 *     }
 *
 *     private static final Unsafe U;
 *     private static final long BALANCE_OFFSET;
 *
 *     static {
 *         try {
 *             // 获取Unsafe实例
 *             Field f = Unsafe.class.getDeclaredField("theUnsafe");
 *             f.setAccessible(true);
 *             U = (Unsafe) f.get(null);
 *
 *             // 获取balance字段的偏移量
 *             BALANCE_OFFSET = U.objectFieldOffset(Account.class.getDeclaredField("balance"));
 *         } catch (Exception e) {
 *             throw new AssertionError(e);
 *         }
 *     }
 *
 *     public static void main(String[] args) {
 *         Account account = new Account();
 *
 *         while (true) {
 *             int o = account.balance; // 当前余额
 *             int n = o + 5;           // 新余额
 *             if (U.compareAndSwapInt(account, BALANCE_OFFSET, o, n)) {
 *                 break; // 如果更新成功，则跳出循环
 *             }
 *         }
 *     }
 * }
 *
 * 请注意，直接使用Unsafe类是不推荐的，因为它可以绕过Java的安全检查并且其API不是官方公开的接口。在实际开发中，更推荐使用AtomicInteger、AtomicLong等原子类或者锁机制来实现线程安全的操作。如果确实需要类似Unsafe提供的低级功能，应该考虑使用VarHandle，它是Java 9引入的一个更加安全和受支持的方式来进行类似的原子操作。
 *
 *
 *
 */

//import jdk.internal.misc.Unsafe;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

// --add-opens java.base/jdk.internal.misc=ALL-UNNAMED
public class SyncVsCas {
//    static final Unsafe U = Unsafe.getUnsafe();
//    static final long BALANCE = U.objectFieldOffset(Account.class, "balance");\



    private static final Unsafe U;

    static {
        try {
            Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
            unsafeField.setAccessible(true);
            U = (Unsafe) unsafeField.get(null);
        } catch (Exception e) {
            throw new RuntimeException("Unable to access Unsafe", e);
        }
    }


    static class Account {
        volatile int balance = 10;
    }

    private static final long BALANCE;

    static {
        try {
            Field balanceField = Account.class.getDeclaredField("balance");
            BALANCE = U.objectFieldOffset(balanceField);
        } catch (NoSuchFieldException e) {
            throw new Error(e);
        }
    }

    private static void showResult(Account account, Thread t1, Thread t2) {
        try {
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println("连个线程都执行结束：");
            LoggerUtils.get().debug("{}", account.balance);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void sync(Account account) {
        Thread t1 = new Thread(() -> {
            synchronized (account) {
                int old = account.balance;
                int n = old - 5;
                System.out.println("减去5");
                account.balance = n;
            }
        },"t1");

        Thread t2 = new Thread(() -> {
            synchronized (account) {
                int o = account.balance;
                System.out.println("加上5");
                int n = o + 5;
                account.balance = n;
            }
        },"t2");

        showResult(account, t1, t2);
    }

    public static void cas(Account account) {
        Thread t1 = new Thread(() -> {
            while (true) {
                int o = account.balance;
                int n = o - 5;
                if (U.compareAndSwapInt(account, BALANCE, o, n)) {
                    System.out.println("nani1");
                    break;
                }
            }
            System.out.println("减去5以后："+account.balance);
        },"t1");

        Thread t2 = new Thread(() -> {
            while (true) {
                int o = account.balance;
                int n = o + 5;
                if (U.compareAndSwapInt(account, BALANCE, o, n)) {
                    System.out.println("nani2");
                    break;
                }
            }
            System.out.println("加上5以后："+account.balance);
        },"t2");

        showResult(account, t1, t2);
    }

    private static void basicCas(Account account) {
        while (true) {
            int o = account.balance;
            int n = o + 5;
            if(U.compareAndSwapInt(account, BALANCE, o, n)){

                break;
            }
        }
        System.out.println(account.balance);
    }

    public static void main(String[] args) {
        Account account = new Account();
        cas(account);
    }


}
